from module.huada.entity.base_entity import BaseEntity
from plugin import MSsqlClient, Config, SchedulerManager, Trigger
from plugin import Mylogger

stationid = "C9AB162E-4712-E411-976E-7427EA38CA2A"
department_cache = {}  # 部门缓存，key为level，value为一个字典，key为部门编码，value为部门客户端id


def get_department_cache(level, externalCode):
    """ 动态更新部门缓存 """
    if not department_cache.__contains__(level):
        department_cache[level] = {}

    if not department_cache[level].__contains__(externalCode):
        department_cache[level][externalCode] = ""

    if department_cache[level][externalCode] == "":
        client = MSsqlClient(charset='cp936', **Config.module_config.huada.client_link)
        results = client.select_to_dict(f"select id from acscon_group where type = 1 and level = {level} and [desc] = '{externalCode}'")
        if len(results) > 0:
            department_cache[level][externalCode] = results[0]['id']


def init_department_cache():
    """ 初始化部门缓存 """
    global department_cache
    client = MSsqlClient(charset='cp936', **Config.module_config.huada.client_link)
    results = client.select_to_dict("select id,[desc],level from acscon_group where type = 1")
    if len(results) > 0:
        department_cache.clear()
        for result in results:
            if not department_cache.__contains__(result['level']):
                department_cache[result['level']] = {}
            department_cache[result['level']][result['desc']] = result['id']
    Mylogger.info(f"部门缓存更新完成，共{len(results)}条数据")


init_department_cache() # 初始化部门缓存一次


class O2Entity(BaseEntity):
    url = "/o2/fobusinessunit"
    table_name = "o2"
    create_table = True
    api_data_list = []
    get_time = "2000-01-01 00:00:00"
    order_by = "lastModifiedDateTime"
    sync_list = []
    write_back_dict = {}

    def __init__(self, **kwargs) -> None:
        # {"externalCode":"B1","headOfUnit":"BGI359","name":"华大研究院","startDate":"2022-04-29","status":"A","cust_isAccountingUnit":"false","cust_costCenter":"","lastModifiedDateTime":"2022-05-17 13:50:42.0","cust_Fun_Tag":"","cust_Bgi_Label":"","financialOfficer":"BGI81"}

        self.externalCode = kwargs.get('externalCode')  # O2编码
        # self.headOfUnit = kwargs.get('headOfUnit')  # O2负责人工号
        self.name = kwargs.get('name')  # O2名称
        # self.startDate = kwargs.get('startDate')  # O2开始日期
        self.status = kwargs.get('status')  # O2状态 A有效 I无效
        # self.cust_isAccountingUnit = kwargs.get('cust_isAccountingUnit')  # 是否会计单位
        # self.cust_costCenter = kwargs.get('cust_costCenter')  # 成本中心
        self.lastModifiedDateTime = kwargs.get('lastModifiedDateTime')  # 最后修改时间
        # self.cust_Fun_Tag = kwargs.get('cust_Fun_Tag')  # 功能标签
        # self.cust_Bgi_Label = kwargs.get('cust_Bgi_Label')  # BGI标签
        # self.financialOfficer = kwargs.get('financialOfficer')  # 财务负责人工号
        self.isdeal = kwargs.get('isdeal') or 0  # 是否处理过，0未处理，1已处理, -n 代表第n次处理失败
        self.id = kwargs.get('id') or 0

    @classmethod
    def do_sync(cls, client: MSsqlClient, objs):
        result_num = [0, 0]  # 写，删
        for obj in objs:
            groupname = obj.externalCode + '-' + obj.name
            result = None
            if obj.status == "A":
                # o2部门有效： 1. 新增部门  2. 修改已有部门名称。
                # 将主键externalCode，写入desc字段，用于判断是新增还是更新

                result = client.execute(f"""
                if not exists (select 1 from acscon_group where [desc] = '{obj.externalCode}' and type = 1 and level = 1)
                begin
                    insert into acscon_group (stationid,type,name,level,[desc],pid) values ('{stationid}',1,'{groupname}',1,'{obj.externalCode}','{stationid}')
                end
                else
                begin
                    update acscon_group set name = '{groupname}' where [desc] = '{obj.externalCode}' and type = 1 and level = 1
                end
                """)
                result_num[0] += result
            elif obj.status == "I":
                # o2部门无效： 1. 删除部门
                result = client.execute(f"delete from acscon_group where [desc] = '{obj.externalCode}' and type = 1 and level = 1")
                if result == 0:
                    # 删除失败，说明不存在该部门
                    result = 1
                    Mylogger.info(f"O2部门{obj.externalCode}不存在，无需删除")
                result_num[1] += result

            if result is not None:
                # 同步成功，key = 1 ,否则isdeal 减一
                key = 1 if result == 1 else (int(obj.isdeal) - 1)
                if not cls.write_back_dict.__contains__(str(key)):
                    cls.write_back_dict[str(key)] = []

                cls.write_back_dict[str(key)].append(str(obj.id))

        Mylogger.info(f"O2部门同步结果：写入{result_num[0]}条，删除{result_num[1]}条")
        return super().do_sync(None, None)


class O3Entity(BaseEntity):
    url = "/o3/fodivision"
    table_name = "o3"
    create_table = True
    api_data_list = []
    get_time = "2000-01-01 00:00:00"
    order_by = "lastModifiedDateTime"
    sync_list = []
    write_back_dict = {}

    def __init__(self, **kwargs) -> None:
        # {"externalCode":"B1AA","headOfUnit":"BGI303","name":"核心平台研发中心","startDate":"2021-12-26","status":"I","cust_isAccountingUnit":"false","cust_costCenter":"","cust_HROfUnit":"","lastModifiedDateTime":"2021-12-26 10:38:56.0","cust_toO2":"B1","cust_Fun_Tag":"","cust_Bgi_Label":"","cust_Default_Head":"","financialOfficer":""}

        self.externalCode = kwargs.get('externalCode')  # O3编码
        # self.headOfUnit = kwargs.get('headOfUnit')  # O3负责人工号
        self.name = kwargs.get('name')  # O3名称
        # self.startDate = kwargs.get('startDate')  # O3开始日期
        self.status = kwargs.get('status')  # O3状态 A有效 I无效
        # self.cust_isAccountingUnit = kwargs.get('cust_isAccountingUnit')  # 是否会计单位
        # self.cust_costCenter = kwargs.get('cust_costCenter')  # 成本中心
        # self.cust_HROfUnit = kwargs.get('cust_HROfUnit')  # HR负责人工号
        self.lastModifiedDateTime = kwargs.get('lastModifiedDateTime')  # 最后修改时间
        self.parentCode = kwargs.get('cust_toO2') or kwargs.get('parentCode')  # 所属O2
        # self.cust_Fun_Tag = kwargs.get('cust_Fun_Tag')  # 功能标签
        # self.cust_Bgi_Label = kwargs.get('cust_Bgi_Label')  # BGI标签
        # self.cust_Default_Head = kwargs.get('cust_Default_Head')  # 默认负责人工号
        # self.financialOfficer = kwargs.get('financialOfficer')  # 财务负责人工号
        self.isdeal = kwargs.get('isdeal') or 0  # 是否处理过，0未处理，1已处理, -n 代表第n次处理失败
        self.id = kwargs.get('id') or 0

    @classmethod
    def do_sync(cls, client: MSsqlClient, objs):
        sync_data(client, objs, 2, cls.write_back_dict)
        return super().do_sync(None, None)


class O4Entity(BaseEntity):
    url = "/o4/fodepartment"
    table_name = "o4"
    create_table = True
    api_data_list = []
    get_time = "2000-01-01 00:00:00"
    order_by = "lastModifiedDateTime"
    sync_list = []
    write_back_dict = {}

    def __init__(self, **kwargs) -> None:
        # {"externalCode":"B1AA01","headOfUnit":"BGI303","name":"核心平台研发中心","startDate":"2021-12-26","status":"I","cust_isAccountingUnit":"false","cust_costCenter":"","cust_HROfUnit":"","lastModifiedDateTime":"2021-12-26 10:38:56.0","cust_toO2":"B1","cust_Fun_Tag":"","cust_Bgi_Label":"","cust_Default_Head":"","financialOfficer":""}

        self.externalCode = kwargs.get('externalCode')  # O4编码
        # self.headOfUnit = kwargs.get('headOfUnit')  # O4负责人工号
        self.name = kwargs.get('name')  # O4名称
        # self.startDate = kwargs.get('startDate')  # O4开始日期
        self.status = kwargs.get('status')  # O4状态 A有效 I无效
        # self.cust_isAccountingUnit = kwargs.get('cust_isAccountingUnit')  # 是否会计单位
        # self.cust_costCenter = kwargs.get('cust_costCenter')  # 成本中心
        # self.cust_HROfUnit = kwargs.get('cust_HROfUnit')  # HR负责人工号
        self.lastModifiedDateTime = kwargs.get('lastModifiedDateTime')  # 最后修改时间
        self.parentCode = kwargs.get('cust_toO3') or kwargs.get('parentCode')  # 所属O3
        # self.cust_Fun_Tag = kwargs.get('cust_Fun_Tag')  # 功能标签
        # self.cust_Bgi_Label = kwargs.get('cust_Bgi_Label')  # BGI标签
        # self.cust_Default_Head = kwargs.get('cust_Default_Head')  # 默认负责人工号
        # self.financialOfficer = kwargs.get('financialOfficer')  # 财务负责人工号
        self.isdeal = kwargs.get('isdeal') or 0  # 是否处理过，0未处理，1已处理, -n 代表第n次处理失败
        self.id = kwargs.get('id') or 0

    @classmethod
    def do_sync(cls, client: MSsqlClient, objs):
        sync_data(client, objs, 3, cls.write_back_dict)
        return super().do_sync(None, None)


class O5Entity(BaseEntity):
    url = "/o5/cust_o5"
    table_name = "o5"
    create_table = True
    api_data_list = []
    get_time = "2000-01-01 00:00:00"
    order_by = "lastModifiedDateTime"
    sync_list = []
    write_back_dict = {}

    def __init__(self, **kwargs) -> None:
        # {"externalCode":"B1AA0101","headOfUnit":"BGI303","name":"核心平台研发中心","startDate":"2021-12-26","status":"I","cust_isAccountingUnit":"false","cust_costCenter":"","cust_HROfUnit":"","lastModifiedDateTime":"2021-12-26 10:38:56.0","cust_toO2":"B1","cust_Fun_Tag":"","cust_Bgi_Label":"","cust_Default_Head":"","financialOfficer":""}

        self.externalCode = kwargs.get('externalCode')  # O5编码
        # self.headOfUnit = kwargs.get('headOfUnit')  # O5负责人工号
        self.name = kwargs.get('externalName') or kwargs.get('name')  # O5名称
        # self.startDate = kwargs.get('startDate')  # O5开始日期
        self.status = kwargs.get('mdfSystemStatus') or kwargs.get('status')  # O5状态 A有效 I无效
        # self.cust_isAccountingUnit = kwargs.get('cust_isAccountingUnit')  # 是否会计单位
        # self.cust_costCenter = kwargs.get('cust_costCenter')  # 成本中心
        # self.cust_HROfUnit = kwargs.get('cust_HROfUnit')  # HR负责人工号
        self.lastModifiedDateTime = kwargs.get('lastModifiedDateTime')  # 最后修改时间
        self.parentCode = kwargs.get('cust_toO4') or kwargs.get('parentCode')  # 所属O4
        # self.cust_Fun_Tag = kwargs.get('cust_Fun_Tag')  # 功能标签
        # self.cust_Bgi_Label = kwargs.get('cust_Bgi_Label')  # BGI标签
        # self.cust_Default_Head = kwargs.get('cust_Default_Head')  # 默认负责人工号
        # self.financialOfficer = kwargs.get('financialOfficer')  # 财务负责人工号
        self.isdeal = kwargs.get('isdeal') or 0  # 是否处理过，0未处理，1已处理, -n 代表第n次处理失败
        self.id = kwargs.get('id') or 0

    @classmethod
    def do_sync(cls, client: MSsqlClient, objs):
        sync_data(client, objs, 4, cls.write_back_dict)
        return super().do_sync(None, None)


class O6Entity(BaseEntity):
    url = "/o6/cust_o6"
    table_name = "o6"
    create_table = True
    api_data_list = []
    get_time = "2000-01-01 00:00:00"
    order_by = "lastModifiedDateTime"
    sync_list = []
    write_back_dict = {}

    def __init__(self, **kwargs) -> None:
        # {"externalCode":"B1AA0101","headOfUnit":"BGI303","name":"核心平台研发中心","startDate":"2021-12-26","status":"I","cust_isAccountingUnit":"false","cust_costCenter":"","cust_HROfUnit":"","lastModifiedDateTime":"2021-12-26 10:38:56.0","cust_toO2":"B1","cust_Fun_Tag":"","cust_Bgi_Label":"","cust_Default_Head":"","financialOfficer":""}

        self.externalCode = kwargs.get('externalCode')  # O5编码
        # self.headOfUnit = kwargs.get('headOfUnit')  # O5负责人工号
        self.name = kwargs.get('externalName') or kwargs.get('name')  # O5名称
        # self.startDate = kwargs.get('startDate')  # O5开始日期
        self.status = kwargs.get('mdfSystemStatus') or kwargs.get('status')  # O5状态 A有效 I无效
        # self.cust_isAccountingUnit = kwargs.get('cust_isAccountingUnit')  # 是否会计单位
        # self.cust_costCenter = kwargs.get('cust_costCenter')  # 成本中心
        # self.cust_HROfUnit = kwargs.get('cust_HROfUnit')  # HR负责人工号
        self.lastModifiedDateTime = kwargs.get('lastModifiedDateTime')  # 最后修改时间
        self.parentCode = kwargs.get('cust_toO5') or kwargs.get('parentCode')  # 所属O4
        # self.cust_Fun_Tag = kwargs.get('cust_Fun_Tag')  # 功能标签
        # self.cust_Bgi_Label = kwargs.get('cust_Bgi_Label')  # BGI标签
        # self.cust_Default_Head = kwargs.get('cust_Default_Head')  # 默认负责人工号
        # self.financialOfficer = kwargs.get('financialOfficer')  # 财务负责人工号
        self.isdeal = kwargs.get('isdeal') or 0  # 是否处理过，0未处理，1已处理, -n 代表第n次处理失败
        self.id = kwargs.get('id') or 0

    @classmethod
    def do_sync(cls, client: MSsqlClient, objs):
        sync_data(client, objs, 5, cls.write_back_dict)
        return super().do_sync(None, None)


class O7Entity(BaseEntity):
    url = "/o7/cust_o7"
    table_name = "o7"
    create_table = True
    api_data_list = []
    get_time = "2000-01-01 00:00:00"  # 上一次获取数据的时间
    order_by = "lastModifiedDateTime"
    sync_list = []
    write_back_dict = {}

    def __init__(self, **kwargs) -> None:
        # {"externalCode":"B1AA0101","headOfUnit":"BGI303","name":"核心平台研发中心","startDate":"2021-12-26","status":"I","cust_isAccountingUnit":"false","cust_costCenter":"","cust_HROfUnit":"","lastModifiedDateTime":"2021-12-26 10:38:56.0","cust_toO2":"B1","cust_Fun_Tag":"","cust_Bgi_Label":"","cust_Default_Head":"","financialOfficer":""}

        self.externalCode = kwargs.get('externalCode')  # O5编码
        # self.headOfUnit = kwargs.get('headOfUnit')  # O5负责人工号
        self.name = kwargs.get('externalName') or kwargs.get('name')  # O5名称
        # self.startDate = kwargs.get('startDate')  # O5开始日期
        self.status = kwargs.get('mdfSystemStatus') or kwargs.get('status')  # O5状态 A有效 I无效
        # self.cust_isAccountingUnit = kwargs.get('cust_isAccountingUnit')  # 是否会计单位
        # self.cust_costCenter = kwargs.get('cust_costCenter')  # 成本中心
        # self.cust_HROfUnit = kwargs.get('cust_HROfUnit')  # HR负责人工号
        self.lastModifiedDateTime = kwargs.get('lastModifiedDateTime')  # 最后修改时间
        self.parentCode = kwargs.get('cust_toO6') or kwargs.get('parentCode')  # 所属O4
        # self.cust_Fun_Tag = kwargs.get('cust_Fun_Tag')  # 功能标签
        # self.cust_Bgi_Label = kwargs.get('cust_Bgi_Label')  # BGI标签
        # self.cust_Default_Head = kwargs.get('cust_Default_Head')  # 默认负责人工号
        # self.financialOfficer = kwargs.get('financialOfficer')  # 财务负责人工号
        self.isdeal = kwargs.get('isdeal') or 0  # 是否处理过，0未处理，1已处理, -n 代表第n次处理失败
        self.id = kwargs.get('id') or 0

    @classmethod
    def do_sync(cls, client: MSsqlClient, objs):
        sync_data(client, objs, 6, cls.write_back_dict)
        return super().do_sync(None, None)


def sync_data(client: MSsqlClient, objs, level, write_back_dict):
    """
    同步数据
    @param:
        client: 数据库连接
        objs: 数据列表
        level: 部门层级,组态的层级
        write_back_dict: 写回字典

    @return:
    """
    result_num = [0, 0]  # 写，删
    for obj in objs:
        parent_code = obj.parentCode
        get_department_cache(level - 1, parent_code)
        groupname = obj.externalCode + '-' + obj.name
        result = None
        if obj.status == "A":
            # o3部门有效： 1. 新增部门  2. 修改已有部门名称。
            # 将主键externalCode，写入desc字段，用于判断是新增还是更新
            if department_cache[level - 1][parent_code] not in (None, ''):  # 父级部门存在

                result = client.execute(f"""
                if not exists (select 1 from acscon_group where [desc] = '{obj.externalCode}' and type = 1 and level = {level})
                begin
                    insert into acscon_group (stationid,type,name,level,[desc],pid) values ('{stationid}',1,'{groupname}',{level},'{obj.externalCode}','{department_cache[level-1][parent_code]}')
                end
                else
                begin
                    update acscon_group set name = '{groupname}' where [desc] = '{obj.externalCode}' and type = 1 and level = {level}
                end
                """)
            else:
                Mylogger.info(f"O{level+1}部门{obj.externalCode}的父级部门{obj.parentCode}不存在，无法新增")
                result = 0
            result_num[0] += result
        elif obj.status == "I":
            # o2部门无效： 1. 删除部门
            result = client.execute(f"delete from acscon_group where [desc] = '{obj.externalCode}' and type = 1 and level = {level}")
            if result == 0:
                # 删除失败，说明不存在该部门
                result = 1
                Mylogger.info(f"O{level+1}部门{obj.externalCode}不存在，无需删除")
            result_num[1] += result

        if result is not None:
            # 同步成功，key = 1 ,否则isdeal 减一
            key = 1 if result == 1 else (int(obj.isdeal) - 1)
            if not write_back_dict.__contains__(str(key)):
                write_back_dict[str(key)] = []

            write_back_dict[str(key)].append(str(obj.id))

    Mylogger.info(f"O{level+1}同步成功结果：写入{result_num[0]}条，删除{result_num[1]}条")